home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 701-725 / 708 / intuisup / intuisup42.lha / Intuisup / source.lha / Gadgets / gadgets1.c < prev    next >
C/C++ Source or Header  |  1992-05-14  |  48KB  |  1,758 lines

  1. /* $Revision Header *** Header built automatically - do not edit! ***********
  2.  *
  3.  *    (C) Copyright 1991 by Torsten Jürgeleit
  4.  *
  5.  *    Name .....: gadgets1.c
  6.  *    Created ..: Thursday 19-Dec-91 20:52:50
  7.  *    Revision .: 9
  8.  *
  9.  *    Date        Author                 Comment
  10.  *    =========   ====================   ====================
  11.  *    14-Apr-92   Torsten Jürgeleit      if flag GADGET_DATA_FLAG_NO_CLEAR
  12.  *                                         set then don't clear area occupied
  13.  *                                         by ISUP object before drawing
  14.  *    30-Apr-92   Torsten Jürgeleit      area gadget occupies now cleared 
  15.  *                                         before diplaying it
  16.  *    28-Apr-92   Torsten Jürgeleit      correct disabling in
  17.  *                                         set_gadget_attributes() if gadgets
  18.  *                                         not displayed -> gl_Window was not
  19.  *                                         defined
  20.  *    20-Apr-92   Torsten Jürgeleit      disable refresh if same entry
  21.  *                                         from list view selected
  22.  *    01-Apr-92   Torsten Jürgeleit      any references to gadget data
  23.  *                                         via gl_Data removed
  24.  *    01-Apr-92   Torsten Jürgeleit      changed parameter size of
  25.  *                                         modify_gadget() for new value of
  26.  *                                         USE_CURRENT_VALUE (1L << 31)
  27.  *    11-Mar-92   Torsten Jürgeleit      guru if toggeling DISABLED of NOT
  28.  *                                         displayed ISUP object via
  29.  *                                         set_gadget_attributes()
  30.  *    24-Jan-92   Torsten Jürgeleit      new function modify_gadget()
  31.  *    28-Dec-91   Torsten Jürgeleit      correct highliting of toggle
  32.  *                                         select buttons
  33.  *    19-Dec-91   Torsten Jürgeleit      Created this file!
  34.  *
  35.  ****************************************************************************
  36.  *
  37.  *    Gadget support routines - part 1
  38.  *
  39.  * $Revision Header ********************************************************/
  40.  
  41.     /* Includes */
  42.  
  43. #include <exec/types.h>
  44. #include <exec/memory.h>
  45. #include <devices/inputevent.h>
  46. #include <intuition/intuition.h>
  47. #ifdef AZTEC_C
  48. #include <functions.h>   /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
  49. #endif
  50. #include <libraries/memwatch.h>   /* header file for memory debug link library (Fish 240) - AFTER functions.h */
  51. #include <string.h>
  52. #include "/render/render.h"
  53. #include "/borders/borders.h"
  54. #include "/texts/texts.h"
  55. #include "/language/language.h"
  56. #include "/pointer/pointer.h"
  57. #include "gadgets.h"
  58. #include "imports.h"
  59.  
  60.     /* Imports */
  61.  
  62. IMPORT struct IntuitionBase  *IntuitionBase;
  63.  
  64.     /* Static data */
  65.  
  66. STATIC struct VisibleGadgetLists  visible_gadget_lists = {
  67.    {   /* struct SignalSemaphore  vg_Semaphore */
  68.       {   /* struct Node  ss_Link */
  69.      NULL, NULL, NT_SEMAPHORE, 0, NULL
  70.       }, 0,
  71.       {   /* struct MinList  ss_WaitQueue */
  72.      (struct MinNode *)&visible_gadget_lists.vg_Semaphore.ss_WaitQueue.mlh_Tail,
  73.      NULL,
  74.      (struct MinNode *)&visible_gadget_lists.vg_Semaphore.ss_WaitQueue.mlh_Head
  75.       },
  76.       {   /* struct SemaphoreRequest  ss_MultipleLink */
  77.      {   /* struct MinNode  sr_Link */
  78.         NULL, NULL
  79.      }, NULL
  80.       }, NULL, -1
  81.    },
  82.    {   /* struct MinList  vg_MinList */
  83.       (struct MinNode *)&visible_gadget_lists.vg_MinList.mlh_Tail,
  84.       NULL,
  85.       (struct MinNode *)&visible_gadget_lists.vg_MinList.mlh_Head
  86.    }, 0
  87. };
  88. BYTE hotkey_id[] = "_";
  89.  
  90.     /* Create gadget list */
  91.  
  92.    struct GadgetList *
  93. create_gadgets(struct RenderInfo  *ri, struct GadgetData  *gd,
  94.            SHORT hoffset, SHORT voffset, BYTE **language_text_array)
  95. {
  96.    USHORT data_entries;
  97.  
  98.    if (ri && ri->ri_ID == ISUP_ID && gd &&
  99.                (data_entries = count_gadget_data_entries(gd))) {
  100.       struct GadgetList  *gl;
  101.       ULONG gl_size = sizeof(struct GadgetList) + (data_entries - 1) *
  102.                         sizeof(struct ExtendedGadget *);
  103.       if (gl = AllocMem(gl_size, (LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
  104.      BYTE  *gadget_buffer;
  105.      ULONG gadget_buffer_size;
  106.  
  107.      gl->gl_RenderInfo        = ri;
  108.      gl->gl_DataEntries       = data_entries;
  109.      gl->gl_LanguageTextArray = language_text_array;
  110.      if ((gadget_buffer_size = get_gadget_buffer_size(gl, gd)) &&
  111.                    (gadget_buffer = AllocMem(gadget_buffer_size,
  112.                      (LONG)MEMF_PUBLIC | MEMF_CLEAR))) {
  113.         BYTE  *image_buffer = NULL;
  114.         ULONG image_buffer_size;
  115.  
  116.         if (image_buffer_size = get_image_buffer_size(gl, gd)) {
  117.            image_buffer = AllocMem(image_buffer_size,
  118.                          (LONG)MEMF_PUBLIC | MEMF_CHIP);
  119.         }
  120.         if (!image_buffer_size || image_buffer) {
  121.  
  122.            /* Init gadget list struct */
  123.            gl->gl_GadgetBuffer     = gadget_buffer;
  124.            gl->gl_GadgetBufferSize = gadget_buffer_size;
  125.            gl->gl_ImageBuffer      = image_buffer;
  126.            gl->gl_ImageBufferSize  = image_buffer_size;
  127.            gl->gl_ID               = ISUP_ID;
  128.            init_gadgets(gl, gd, hoffset, voffset);
  129.            return(gl);
  130.         }
  131.         FreeMem(gadget_buffer, gadget_buffer_size);
  132.      }
  133.      FreeMem(gl, gl_size);
  134.       }
  135.    }
  136.    return(NULL);
  137. }
  138.     /* Free gadget list */
  139.  
  140.    VOID
  141. free_gadgets(struct GadgetList  *gl)
  142. {
  143.    if (gl && gl->gl_ID == ISUP_ID) {
  144.       USHORT i, data_entries = gl->gl_DataEntries;
  145.  
  146.       if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  147.      remove_gadgets(gl);
  148.       }
  149.  
  150.       /* Close fonts */
  151.       for (i = 0; i < data_entries; i++) {
  152.      struct ExtendedGadget  *egad = gl->gl_Gadgets[i];
  153.  
  154.      if (egad->eg_Flags & EXTENDED_GADGET_FLAG_CLOSE_FONT) {
  155.         CloseFont(egad->eg_TextFont);
  156.      }
  157.       }
  158.  
  159.       /* Free buffers */
  160.       FreeMem(gl->gl_GadgetBuffer, gl->gl_GadgetBufferSize);
  161.       if (gl->gl_ImageBufferSize) {
  162.      FreeMem(gl->gl_ImageBuffer, gl->gl_ImageBufferSize);
  163.       }
  164.       FreeMem(gl, (LONG)(sizeof(struct GadgetList) +
  165.            (gl->gl_DataEntries - 1) * sizeof(struct ExtendedGadget *)));
  166.    }
  167. }
  168.     /* Display gadget list */
  169.  
  170.    VOID
  171. display_gadgets(struct Window  *win, struct GadgetList  *gl)
  172. {
  173.    if (win && gl && gl->gl_ID == ISUP_ID &&
  174.                  !(gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
  175.       struct RenderInfo          *ri = gl->gl_RenderInfo;
  176.       struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  177.       struct ExtendedGadget      *last_egad = NULL;
  178.       USHORT i, data_entries = gl->gl_DataEntries,
  179.          clear_flags = (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW ?
  180.                     0 : CLEAR_WINDOW_FLAG_ABSOLUTE_POS);
  181.       /* Mark gadget list as displayed */
  182.       gl->gl_Window = win;
  183.       gl->gl_Flags |= GADGET_LIST_FLAG_DISPLAYED;
  184.  
  185.       /* Increment visible gadget list counter */
  186.       ObtainSemaphore(&vg->vg_Semaphore);
  187.       AddTail((struct List *)&vg->vg_MinList, (struct Node *)&gl->gl_MinNode);
  188.       vg->vg_Count++;
  189.       ReleaseSemaphore(&vg->vg_Semaphore);
  190.  
  191.       /* Link gadget list */
  192.       for (i = 0; i < data_entries; i++) {
  193.      struct ExtendedGadget  *egad = gl->gl_Gadgets[i];
  194.  
  195.      /* First clear area occupied by this ISUP object */
  196.      if (!(egad->eg_DataFlags & GADGET_DATA_FLAG_NO_CLEAR)) {
  197.         clear_window(ri, win, egad->eg_BorderLeftEdge,
  198.                    egad->eg_BorderTopEdge, egad->eg_BorderWidth,
  199.                       egad->eg_BorderHeight, clear_flags);
  200.      }
  201.  
  202.      /* Move mouse pointer to this ISUP object */
  203.      if (egad->eg_DataFlags & GADGET_DATA_FLAG_MOVE_POINTER) {
  204.         struct Gadget  *gad = &egad->eg_Gadget;
  205.  
  206.         move_mouse_pointer(win, gad->LeftEdge + gad->Width / 2,
  207.                      gad->TopEdge + gad->Height / 2, FALSE);
  208.      }
  209.  
  210.      /* Link gadgets of this ISUP object */
  211.      do {
  212.         if (last_egad) {
  213.            last_egad->eg_Gadget.NextGadget = &egad->eg_Gadget;
  214.         }
  215.         last_egad = egad;
  216.      } while (egad = egad->eg_NextGadget);
  217.       }
  218.       AddGList(win, &gl->gl_Gadgets[0]->eg_Gadget, -1L, -1L, (LONG)NULL);
  219.       refresh_gadgets(gl);
  220.    }
  221. }
  222.     /* Refresh gadget list */
  223.  
  224.    VOID
  225. refresh_gadgets(struct GadgetList  *gl)
  226. {
  227.    if (gl && gl->gl_ID == ISUP_ID &&
  228.                   (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
  229.       USHORT i, data_entries = gl->gl_DataEntries;
  230.  
  231.       for (i = 0; i < data_entries; i++) {
  232.      refresh_gadget(gl->gl_Gadgets[i]);
  233.       }
  234.    }
  235. }
  236.     /* Modify gadget position and dimension */
  237.  
  238.    VOID
  239. modify_gadget(struct GadgetList  *gl, USHORT data_entry, LONG left_edge,
  240.                    LONG top_edge, ULONG width, ULONG height)
  241. {
  242.    if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries &&
  243.      (left_edge != USE_CURRENT_VALUE || top_edge != USE_CURRENT_VALUE ||
  244.            width != USE_CURRENT_VALUE || height != USE_CURRENT_VALUE)) {
  245.       struct ExtendedGadget  *egad = gl->gl_Gadgets[data_entry];
  246.       SHORT dx, dy;
  247.  
  248.       /* Clear old gadget */
  249.       if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  250.      struct RenderInfo  *ri = gl->gl_RenderInfo;
  251.      struct RastPort    *rp = gl->gl_Window->RPort;
  252.      SHORT x, y;
  253.  
  254.      SetAPen(rp, (LONG)ri->ri_BackPen);
  255.      SetDrMd(rp, (LONG)JAM1);
  256.  
  257.      /* Clear gadget */
  258.      x = egad->eg_BorderLeftEdge;
  259.      y = egad->eg_BorderTopEdge;
  260.  
  261.      /* Inner window position needed ? */
  262.      if (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW) {
  263.         x += ri->ri_WindowBorderLeft;
  264.         y += ri->ri_WindowBorderTop;
  265.      }
  266.      RectFill(rp, (LONG)x, (LONG)y, (LONG)(x + egad->eg_BorderWidth - 1),
  267.                      (LONG)(y + egad->eg_BorderHeight - 1));
  268.      /* Clear gadget text - don't forget underscore !!! */
  269.      if (egad->eg_Text) {
  270.         x = egad->eg_Gadget.LeftEdge + egad->eg_TextLeftEdge;
  271.         y = egad->eg_Gadget.TopEdge + egad->eg_TextTopEdge;
  272.         RectFill(rp, (LONG)x, (LONG)y, (LONG)(x + egad->eg_TextWidth - 1),
  273.                    (LONG)(y + egad->eg_TextFont->tf_YSize));
  274.      }
  275.       }
  276.  
  277.       /* Calc difference to old position */
  278.       if (left_edge == USE_CURRENT_VALUE) {
  279.      dx = 0;
  280.       } else {
  281.      dx = left_edge - egad->eg_BorderLeftEdge;
  282.       }
  283.       if (top_edge == USE_CURRENT_VALUE) {
  284.      dy = 0;
  285.       } else {
  286.      dy = top_edge - egad->eg_BorderTopEdge;
  287.       }
  288.  
  289.       /* Move gadget */
  290.       if (dx || dy) {
  291.      struct ExtendedGadget  *eg = egad;
  292.      VOID *data = egad + 1;
  293.  
  294.      /* Move all extended gadgets belonging to this object */
  295.      do {
  296.         eg->eg_BorderLeftEdge  += dx;
  297.         eg->eg_BorderTopEdge   += dy;
  298.         eg->eg_Gadget.LeftEdge += dx;
  299.         eg->eg_Gadget.TopEdge  += dy;
  300.          } while (eg = eg->eg_NextGadget);
  301.  
  302.      /* Move special gadget data */
  303.      switch (egad->eg_Type) {
  304.         case EXTENDED_GADGET_TYPE_CYCLE :
  305.            ((struct CycleData *)data)->cy_LeftEdge += dx;
  306.            ((struct CycleData *)data)->cy_TopEdge  += dy;
  307.            break;
  308.  
  309.         case EXTENDED_GADGET_TYPE_COUNT :
  310.            ((struct CountData *)data)->co_LeftEdge += dx;
  311.            ((struct CountData *)data)->co_TopEdge  += dy;
  312.            break;
  313.  
  314.         case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
  315.            ((struct ListViewData *)data)->lv_LeftEdge += dx;
  316.            ((struct ListViewData *)data)->lv_TopEdge  += dy;
  317.            break;
  318.      }
  319.       }
  320.  
  321.       /* Calc difference to old dimension */
  322.       if (width == USE_CURRENT_VALUE) {
  323.      dx = 0;
  324.       } else {
  325.      dx = width - egad->eg_BorderWidth;
  326.       }
  327.       if (height == USE_CURRENT_VALUE) {
  328.      dy = 0;
  329.       } else {
  330.      dy = height - egad->eg_BorderHeight;
  331.       }
  332.  
  333.       /* Resize only some gadgets */
  334.       if (dx || dy) {
  335.      struct Border  *border1, *border2 = NULL;
  336.      USHORT border1_type, border2_type;
  337.      ULONG  flags = egad->eg_DataFlags;
  338.      BOOL   resize = FALSE;
  339.  
  340.      switch (egad->eg_Type) {
  341.         case EXTENDED_GADGET_TYPE_BUTTON :
  342.            if (!(flags & GADGET_DATA_FLAG_BUTTON_IMAGE)) {
  343.           border1_type = BORDER_DATA_TYPE_BOX1_OUT;
  344.           border1      = (struct Border *)egad->eg_Gadget.GadgetRender;
  345.           if (!(flags & GADGET_DATA_FLAG_HIGH_COMP)) {
  346.              border2_type = BORDER_DATA_TYPE_BOX1_IN;
  347.              border2      = (struct Border *)egad->eg_Gadget.SelectRender;
  348.           }
  349.           resize       = TRUE;
  350.            }
  351.            break;
  352.  
  353.         case EXTENDED_GADGET_TYPE_SLIDER_PROP :
  354.            border1_type = BORDER_DATA_TYPE_BOX1_OUT;
  355.            border1      = (struct Border *)egad->eg_Render;
  356.            resize       = TRUE;
  357.            break;
  358.  
  359.         case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
  360.            if (flags & GADGET_DATA_FLAG_SCROLLER_NO_ARROWS) {
  361.           border1_type = BORDER_DATA_TYPE_BOX1_OUT;
  362.           border1      = (struct Border *)egad->eg_Render;
  363.           resize       = TRUE;
  364.            }
  365.            break;
  366.      }
  367.      if (resize == TRUE) {
  368.         
  369.         /* Resize gadget */
  370.         egad->eg_BorderWidth   += dx;
  371.         egad->eg_BorderHeight  += dy;
  372.         egad->eg_Gadget.Width  += dx;
  373.         egad->eg_Gadget.Height += dy;
  374.  
  375.         /* Resize gadget text */
  376.         if (egad->eg_Text) {
  377.  
  378.            /* Change horizontal pos */
  379.            if (flags & GADGET_DATA_FLAG_TEXT_RIGHT) {
  380.           egad->eg_TextLeftEdge += dx;
  381.            } else {
  382.           if (!(flags & GADGET_DATA_FLAG_TEXT_LEFT)) {
  383.              egad->eg_TextLeftEdge += dx / 2;
  384.           }
  385.            }
  386.  
  387.            /* Change vertical pos */
  388.            if (flags & GADGET_DATA_FLAG_TEXT_BELOW) {
  389.           egad->eg_TextTopEdge += dy;
  390.            } else {
  391.           if (!(flags & GADGET_DATA_FLAG_TEXT_ABOVE)) {
  392.              egad->eg_TextTopEdge += dy / 2;
  393.           }
  394.            }
  395.         }
  396.  
  397.         /* Resize border */
  398.         if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  399.            if (border1) {
  400.           resize_border(border1, egad->eg_BorderWidth,
  401.                        egad->eg_BorderHeight, border1_type);
  402.            }
  403.            if (border2) {
  404.           resize_border(border2, egad->eg_BorderWidth,
  405.                        egad->eg_BorderHeight, border2_type);
  406.            }
  407.         }
  408.      }
  409.       }
  410.  
  411.       /* Finally refresh modified gadget */
  412.       refresh_gadget(egad);
  413.    }
  414. }
  415.     /* Set gadget attributes */
  416.  
  417.    ULONG
  418. set_gadget_attributes(struct GadgetList  *gl, USHORT data_entry,
  419.     ULONG flag_mask, ULONG flag_bits, ULONG data1, ULONG data2, VOID *data3)
  420. {
  421.    ULONG value = 0;
  422.  
  423.    if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries) {
  424.       struct ExtendedGadget  *egad = gl->gl_Gadgets[data_entry];
  425.       struct Gadget          *gad = &egad->eg_Gadget;
  426.       USHORT type = egad->eg_DataType;
  427.       ULONG  flags = egad->eg_DataFlags;
  428.       BOOL   refresh = FALSE;
  429.  
  430.       /* Change gadget data flags */
  431.       if (flag_mask) {
  432.      ULONG  mask;
  433.      USHORT i;
  434.  
  435.      /* Change gadget data flags according to flag mask */
  436.      for (i = 0, mask = 1; i < MAX_DATA_FLAG_BITS; i++, mask <<= 1) {
  437.  
  438.         /* Check if flag bit set */
  439.         if (flag_mask & mask) {
  440.            BOOL change = FALSE;
  441.  
  442.            /* Change flag only if changeable and valid for gadget type */
  443.            switch (mask) {
  444.           case GADGET_DATA_FLAG_DISABLED :
  445.  
  446.              /* Toggle able state of gadget */
  447.              if ((flags & mask) != (flag_bits & mask)) {
  448.             struct RastPort        *rp;   /* init later !!! */
  449.             struct ExtendedGadget  *temp_egad = egad;
  450.             UBYTE displayed = gl->gl_Flags &
  451.                          GADGET_LIST_FLAG_DISPLAYED;
  452.             /* Set draw mode and color for clearing enabled select box */
  453.             if (displayed &&
  454.                       (flags & GADGET_DATA_FLAG_DISABLED)) {
  455.                rp = gl->gl_Window->RPort;   /* ONLY if displayed then gl_Window is valid !!!*/
  456.                SetDrMd(rp, (LONG)JAM1);
  457.                SetAPen(rp, (LONG)gl->gl_RenderInfo->ri_BackPen);
  458.             }
  459.  
  460.             /* Toggle able state of ALL gadgets belonging to ISUP object */
  461.             do {
  462.                struct Gadget  *temp_gad = &temp_egad->eg_Gadget;
  463.  
  464.                if (flags & GADGET_DATA_FLAG_DISABLED) {
  465.                   temp_gad->Flags &= ~GADGDISABLED;
  466.  
  467.                   /* Clear ghosted gadget select box */
  468.                   if (displayed) {
  469.                  RectFill(rp, (LONG)temp_gad->LeftEdge,
  470.                             (LONG)temp_gad->TopEdge,
  471.                          (LONG)(temp_gad->LeftEdge +
  472.                                temp_gad->Width - 1),
  473.                           (LONG)(temp_gad->TopEdge +
  474.                              temp_gad->Height - 1));
  475.                   }
  476.                } else {
  477.                   temp_gad->Flags |= GADGDISABLED;
  478.                }
  479.             } while (temp_egad = temp_egad->eg_NextGadget);
  480.  
  481.             /* Refresh gadget before leaving function */
  482.             refresh = TRUE;
  483.             change  = TRUE;
  484.              }
  485.              break;
  486.  
  487.           case GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE :
  488.              if (type == GADGET_DATA_TYPE_STRING ||
  489.                      type == GADGET_DATA_TYPE_INTEGER) {
  490.             change = TRUE;
  491.              }
  492.              break;
  493.  
  494.           case GADGET_DATA_FLAG_STRING_UNSIGNED_DEC :
  495.              if (type == GADGET_DATA_TYPE_STRING) {
  496.             change = TRUE;
  497.              }
  498.              break;
  499.  
  500.           case GADGET_DATA_FLAG_STRING_SIGNED_DEC :
  501.              if (type == GADGET_DATA_TYPE_STRING) {
  502.             change = TRUE;
  503.              }
  504.              break;
  505.  
  506.           case GADGET_DATA_FLAG_STRING_HEX :
  507.              if (type == GADGET_DATA_TYPE_STRING) {
  508.             change = TRUE;
  509.              }
  510.              break;
  511.  
  512.           case GADGET_DATA_FLAG_STRING_BIN :
  513.              if (type == GADGET_DATA_TYPE_STRING) {
  514.             change = TRUE;
  515.              }
  516.              break;
  517.  
  518.           case GADGET_DATA_FLAG_MOVE_POINTER :
  519.              change = TRUE;
  520.              break;
  521.            }
  522.  
  523.            /* Change flag bit if neccessary */
  524.            if (change == TRUE) {
  525.           flags &= ~mask;
  526.           flags |= flag_bits & mask;
  527.            }
  528.         }
  529.      }
  530.  
  531.      /* Save changed gadget data flags */
  532.      egad->eg_DataFlags = flags;
  533.       }
  534.  
  535.       /* Change special gadget data */
  536.       if (data1 != USE_CURRENT_VALUE || data2 != USE_CURRENT_VALUE ||
  537.                        data3 != (VOID *)USE_CURRENT_VALUE) {
  538.      struct MXData        *mx;
  539.      struct SliderData    *sl;
  540.      struct ScrollerData  *sc;
  541.      struct CycleData     *cy;
  542.      struct CountData     *co;
  543.      struct ListViewData  *lv;
  544.      struct PaletteData   *pd;
  545.      struct StringInfo    *sinfo;
  546.      VOID  *data = (VOID *)(egad + 1);
  547.      BYTE  *buffer;
  548.      ULONG min, max, num;
  549.  
  550.      switch (type) {
  551.         case GADGET_DATA_TYPE_BUTTON :
  552.            if (gad->Activation & TOGGLESELECT) {
  553.           if (gad->Flags & SELECTED) {
  554.              value = 1;
  555.           }
  556.           if (data1 != USE_CURRENT_VALUE) {
  557.              if (data1) {
  558.             gad->Flags |= SELECTED;
  559.              } else {
  560.             if (gad->Flags & SELECTED) {
  561.  
  562.                /* Prepare gadget state manually (unselected) */
  563.                change_gadget(egad);
  564.             }
  565.             gad->Flags &= ~SELECTED;
  566.              }
  567.              change_gadget(egad);
  568.           }
  569.            }
  570.            break;
  571.  
  572.         case GADGET_DATA_TYPE_CHECK :
  573.            if (gad->Flags & SELECTED) {
  574.           value = 1;
  575.            }
  576.            if (data1 != USE_CURRENT_VALUE) {
  577.           if (data1) {
  578.              gad->Flags |= SELECTED;
  579.           } else {
  580.              gad->Flags &= ~SELECTED;
  581.           }
  582.           change_gadget(egad);
  583.            }
  584.            break;
  585.  
  586.         case GADGET_DATA_TYPE_MX :
  587.            mx    = data;
  588.            value = mx->mx_ActiveEntry;
  589.            if (data2 != USE_CURRENT_VALUE) {
  590.           max = mx->mx_TextEntries;
  591.           num = data2;
  592.           if (num >= max) {
  593.              num = max - 1;   /* activate last entry */
  594.           }
  595.           mx->mx_ActiveEntry = num;
  596.           change_gadget(egad);
  597.            }
  598.            break;
  599.  
  600.         case GADGET_DATA_TYPE_STRING :
  601.         case GADGET_DATA_TYPE_INTEGER :
  602.            sinfo  = (struct StringInfo *)gad->SpecialInfo;
  603.            buffer = (BYTE *)sinfo->Buffer;
  604.            if (type == GADGET_DATA_TYPE_STRING) {
  605.           value = (ULONG)buffer;
  606.            } else {
  607.           value = sinfo->LongInt;
  608.            }
  609.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  610.           BYTE *input = data3;
  611.  
  612.           max = sinfo->MaxChars;
  613.           if (type == GADGET_DATA_TYPE_STRING) {
  614.  
  615.              /* Convert number for string input gadget */
  616.              if (flags & GADGET_DATA_FLAG_STRING_UNSIGNED_DEC) {
  617.             if ((LONG)input != -1L) {
  618.                min = convert_unsigned_dec((ULONG)input, buffer,
  619.                              DEC_NUM_CONVERT_FLAGS);
  620.             } else {
  621.                min = 0;
  622.             }
  623.              } else {
  624.             if (flags & GADGET_DATA_FLAG_STRING_SIGNED_DEC) {
  625.                if ((LONG)input != -1L) {
  626.                   min = convert_signed_dec((ULONG)input,
  627.                          buffer, DEC_NUM_CONVERT_FLAGS);
  628.                } else {
  629.                   min = 0;
  630.                }
  631.             } else {
  632.                if (flags & GADGET_DATA_FLAG_STRING_HEX) {
  633.                   if ((LONG)input != -1L) {
  634.                  min = convert_hex((ULONG)input, buffer,
  635.                              HEX_NUM_CONVERT_FLAGS);
  636.                   } else {
  637.                  min = 0;
  638.                   }
  639.                } else {
  640.                   if (flags & GADGET_DATA_FLAG_STRING_BIN) {
  641.                  if ((LONG)input != -1L) {
  642.                     min = convert_bin((ULONG)input, buffer,
  643.                              BIN_NUM_CONVERT_FLAGS);
  644.                  } else {
  645.                     min = 0;
  646.                  }
  647.                   } else {
  648.                  if (input) {
  649.                     if ((min = strlen(input)) > max) {
  650.                        min = max;
  651.                     }
  652.                     strncpy(buffer, input, (size_t)min);
  653.                  } else {
  654.                     min = 0;
  655.                  }
  656.                   }
  657.                }
  658.             }
  659.              }
  660.           } else {
  661.  
  662.              /* Convert number for integer input gadget */
  663.              if ((LONG)input != -1L) {
  664.             min = convert_unsigned_dec((ULONG)input, buffer, 0);
  665.              } else {
  666.             min = 0;
  667.              }
  668.           }
  669.           *(buffer + min)  = '\0';   /* mark end of string */
  670.           sinfo->BufferPos = 0;
  671.           change_gadget(egad);
  672.            }
  673.            break;
  674.  
  675.         case GADGET_DATA_TYPE_SLIDER :
  676.            sl    = data;
  677.            value = sl->sl_Level;
  678.            if (data1 != USE_CURRENT_VALUE) {
  679.           min = sl->sl_Min = data1;
  680.            } else {
  681.           min = sl->sl_Min;
  682.            }
  683.            if (data2 != USE_CURRENT_VALUE) {
  684.           max = sl->sl_Max = data2;
  685.            } else {
  686.           max = sl->sl_Max;
  687.            }
  688.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  689.           num = (ULONG)data3;
  690.            } else {
  691.           num = sl->sl_Level;
  692.            }
  693.            if ((LONG)num < (LONG)min) {
  694.           num = min;
  695.            } else {
  696.           if ((LONG)num > (LONG)max) {
  697.              num = max;
  698.           }
  699.            }
  700.            sl->sl_Level = num;
  701.            change_gadget(egad);
  702.            break;
  703.  
  704.         case GADGET_DATA_TYPE_SCROLLER :
  705.            sc    = data;
  706.            value = sc->sc_Top;
  707.            if (data1 != USE_CURRENT_VALUE) {
  708.           min = sc->sc_Visible = data1;
  709.            } else {
  710.           min = sc->sc_Visible;
  711.            }
  712.            if (data2 != USE_CURRENT_VALUE) {
  713.           max = sc->sc_Total = data2;
  714.            } else {
  715.           max = sc->sc_Total;
  716.            }
  717.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  718.           num = (ULONG)data3;
  719.            } else {
  720.           num = sc->sc_Top;
  721.            }
  722.            if (num >= max || (max - num) < min) {
  723.           num = (max > min ? max - min : min - max);
  724.            }
  725.            sc->sc_Top = num;
  726.            change_gadget(egad);
  727.            break;
  728.  
  729.         case GADGET_DATA_TYPE_CYCLE :
  730.            cy    = data;
  731.            value = cy->cy_ActiveEntry;
  732.            if (data2 != USE_CURRENT_VALUE) {
  733.           max = cy->cy_TextEntries;
  734.           num = data2;
  735.           if (num > max) {
  736.              num = max;   /* activate last entry */
  737.           }
  738.           cy->cy_ActiveEntry = num;
  739.           change_gadget(egad);
  740.            }
  741.            break;
  742.  
  743.         case GADGET_DATA_TYPE_COUNT :
  744.            co    = data;
  745.            value = co->co_Value;
  746.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  747.           min = co->co_Min;
  748.           max = co->co_Max;
  749.           num = (ULONG)data3;
  750.           if ((LONG)num < (LONG)min) {
  751.              num = min;
  752.           } else {
  753.              if ((LONG)num > (LONG)max) {
  754.             num = max;
  755.              }
  756.           }
  757.           co->co_Value = num;
  758.           change_gadget(egad);
  759.            }
  760.            break;
  761.  
  762.         case GADGET_DATA_TYPE_LISTVIEW :
  763.            lv = data;
  764.            if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  765.           value = lv->lv_SelectedEntry;
  766.            } else {
  767.           value = lv->lv_TopEntry;
  768.            }
  769.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  770.           struct List  *list = data3;
  771.           struct Node  *node;
  772.  
  773.           /* Count list nodes */
  774.           max = 0;
  775.           if (list) {
  776.              node = list->lh_Head;
  777.              while (node = node->ln_Succ) {
  778.             max++;
  779.              }
  780.           }
  781.           lv->lv_List        = list;
  782.           lv->lv_ListEntries = max;
  783.            }
  784.            if (data2 != USE_CURRENT_VALUE ||
  785.                     (ULONG)data3 != USE_CURRENT_VALUE) {
  786.           struct List  *list = data3;
  787.           struct Node  *node;
  788.           ULONG sel;
  789.  
  790.           list = lv->lv_List;
  791.           min  = lv->lv_VisibleEntries;
  792.           max  = lv->lv_ListEntries;
  793.  
  794.           /* Search top list node */
  795.           if (!max) {
  796.              sel  = 0;
  797.              num  = 0;
  798.              node = NULL;
  799.           } else {
  800.              if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  801.  
  802.             /* Calc correct top entry for selected entry */
  803.             if (data2 != USE_CURRENT_VALUE) {
  804.                sel = data2;
  805.             } else {
  806.                sel = lv->lv_SelectedEntry;
  807.             }
  808.             if (sel >= max) {
  809.                sel = max - 1;
  810.             }
  811.             if (sel && max > min) {
  812.                if (sel > (max - min)) {
  813.                   ULONG i;
  814.  
  815.                   num  = max - min;
  816.                   node = list->lh_TailPred;
  817.                   for (i = max - num - 1; i; i--) {
  818.                  node = node->ln_Pred;
  819.                   }
  820.                } else {
  821.                   node = list->lh_Head;
  822.                   if (sel > (min >> 1)) {
  823.                  ULONG i;
  824.  
  825.                  num = sel - (min >> 1);
  826.                  for (i = 0; i < num; i++) {
  827.                     node = node->ln_Succ;
  828.                  }
  829.                   } else {
  830.                  num = 0;
  831.                   }
  832.                }
  833.             } else {
  834.                num  = 0;
  835.                node = list->lh_Head;
  836.             }
  837.              } else {
  838.  
  839.             /* Calc top entry ignoring selected entry */
  840.             if (data2 != USE_CURRENT_VALUE) {
  841.                num = data2;
  842.             } else {
  843.                num = lv->lv_TopEntry;
  844.             }
  845.             if (num && max > min) {
  846.                if (num > max || (max - num) < min) {
  847.                   ULONG i;
  848.  
  849.                   num  = max - min;
  850.                   node = list->lh_TailPred;
  851.                   for (i = max - num - 1; i; i--) {
  852.                  node = node->ln_Pred;
  853.                   }
  854.                } else {
  855.                   ULONG i;
  856.  
  857.                   node = list->lh_Head;
  858.                   for (i = 0; i < num; i++) {
  859.                  node = node->ln_Succ;
  860.                       }
  861.                }
  862.             } else {
  863.                num  = 0;
  864.                node = list->lh_Head;
  865.             }
  866.             sel = num;
  867.              }
  868.           }
  869.  
  870.           /* Init list view data */
  871.           lv->lv_TopNode       = node;
  872.           lv->lv_TopEntry      = num;
  873.           lv->lv_SelectedEntry = sel;
  874.           change_gadget(egad);   /* before changing list entry gadget flags !!! */
  875.  
  876.           /* Set GADGHNONE flag for all entry gadgets without list node */
  877.           if (!(flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY)) {
  878.              struct ExtendedGadget  *temp_egad;
  879.              USHORT i;
  880.  
  881.              /* Get ptr to first entry gadget */
  882.              temp_egad = egad->eg_NextGadget->eg_NextGadget->eg_NextGadget;
  883.              for (i = 0; i < min; i++, num++) {
  884.             struct Gadget  *temp_gad = &temp_egad->eg_Gadget;
  885.  
  886.             if (num < max) {
  887.                temp_gad->Flags = (temp_gad->Flags &
  888.                          ~GADGHIGHBITS) | GADGHCOMP;
  889.             } else {
  890.                temp_gad->Flags = (temp_gad->Flags &
  891.                          ~GADGHIGHBITS) | GADGHNONE;
  892.             }
  893.             temp_egad = temp_egad->eg_NextGadget;
  894.              }
  895.           }
  896.            }
  897.            break;
  898.  
  899.         case GADGET_DATA_TYPE_PALETTE :
  900.            pd    = data;
  901.            value = pd->pd_ActiveColor;
  902.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  903.           min = pd->pd_ColorOffset;
  904.           max = pd->pd_MaxColors;
  905.           num = (ULONG)data3;
  906.           if (num < min) {
  907.              num = min;
  908.           } else {
  909.              if (num >= (max + min)) {
  910.             num = max + min - 1;
  911.              }
  912.           }
  913.           pd->pd_ActiveColor = num;
  914.           change_gadget(egad);
  915.            }
  916.            break;
  917.      }
  918.       }
  919.  
  920.       /* Finally refresh gadget if necessary */
  921.       if (refresh == TRUE) {
  922.      refresh_gadget(egad);
  923.       }
  924.    }
  925.    return(value);
  926. }
  927.     /* Activate string or integer imput gadget */
  928.  
  929.    VOID
  930. activate_input_gadget(struct GadgetList  *gl, USHORT data_entry)
  931. {
  932.    if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries &&
  933.                   (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
  934.       struct ExtendedGadget  *egad = gl->gl_Gadgets[data_entry];
  935.       USHORT type = egad->eg_DataType;
  936.  
  937.       if (type == GADGET_DATA_TYPE_STRING ||
  938.                      type == GADGET_DATA_TYPE_INTEGER) {
  939.      struct Gadget  *gad = &egad->eg_Gadget;
  940.  
  941.      /* If selected input gadget disabled then activate next one */
  942.      if (gad->Flags & GADGDISABLED) {
  943.         if (egad->eg_DataFlags & GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE) {
  944.            struct InputData  *id = (struct InputData  *)(egad + 1);
  945.  
  946.            /* !!! Recurrence (in german: Rekursion) !!! */
  947.            activate_input_gadget(gl, id->id_ActivateNext);
  948.         }
  949.      } else {
  950.         struct Window  *win = gl->gl_Window;
  951.  
  952.         /* First bring screen + window to front */
  953.         if (IntuitionBase->ActiveScreen != win->WScreen) {
  954.            ScreenToFront(win->WScreen);
  955.         }
  956.  
  957.         /* Now activate window + input gadget */
  958.         if (IntuitionBase->ActiveWindow != win) {
  959.            WindowToFront(win);
  960.            ActivateWindow(win);
  961.            timer_delay(0L, 500000L);
  962.         }
  963.         ActivateGadget(gad, win, (LONG)NULL);
  964.      }
  965.       }
  966.    }
  967. }
  968.     /* Return gadget address */
  969.  
  970.    struct Gadget *
  971. gadget_address(struct GadgetList  *gl, USHORT data_entry)
  972. {
  973.    struct Gadget  *gad = NULL;
  974.  
  975.    if (gl && gl->gl_ID == ISUP_ID && data_entry < gl->gl_DataEntries) {
  976.       gad = &gl->gl_Gadgets[data_entry]->eg_Gadget;
  977.    }
  978.    return(gad);
  979. }
  980.     /* Remove gadget list from display */
  981.  
  982.    struct Window *
  983. remove_gadgets(struct GadgetList  *gl)
  984. {
  985.    struct Window  *win = NULL;
  986.  
  987.    if (gl && gl->gl_ID == ISUP_ID &&
  988.                   (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
  989.       struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  990.       struct IntuiMessage        *succ, *msg;
  991.       USHORT i, data_entries = gl->gl_DataEntries;
  992.  
  993.       /* Mark gadget list as not displayed */
  994.       win           = gl->gl_Window;
  995.       gl->gl_Window = NULL;
  996.       gl->gl_Flags &= ~GADGET_LIST_FLAG_DISPLAYED;
  997.  
  998.       /* Decrement visible gadget list counter */
  999.       ObtainSemaphore(&vg->vg_Semaphore);
  1000.       Remove((struct Node *)&gl->gl_MinNode);
  1001.       vg->vg_Count--;
  1002.       ReleaseSemaphore(&vg->vg_Semaphore);
  1003.  
  1004.       /* Remove gadgets from windows gadget list */
  1005.       for (i = 0; i < data_entries; i++) {
  1006.      struct ExtendedGadget  *egad = gl->gl_Gadgets[i];
  1007.  
  1008.      do {
  1009.         RemoveGList(win, &egad->eg_Gadget, 1L);
  1010.      } while (egad = egad->eg_NextGadget);
  1011.       }
  1012.  
  1013.       /* Reply all ISUP intuition messages belonging to given gadget list */
  1014.       Forbid();
  1015.       msg = (struct IntuiMessage *)win->UserPort->mp_MsgList.lh_Head;
  1016.       while (succ = (struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ) {
  1017.      if (msg->Class == ISUP_ID &&
  1018.                   msg->SpecialLink == (struct IntuiMessage *)gl) {
  1019.         Remove((struct Node *)msg);
  1020.         reply_msg(msg);
  1021.      }
  1022.      msg = succ;
  1023.       }
  1024.       Permit();
  1025.    }
  1026.    return(win);
  1027. }
  1028.     /* Get intuition msg and perform any action to isup gadgets */
  1029.  
  1030.    struct IntuiMessage *
  1031. get_msg(struct MsgPort  *uport)
  1032. {
  1033.    struct IntuiMessage  *imsg = NULL;
  1034.  
  1035.    if (uport) {
  1036.       struct IntuiMessage  *real_imsg;
  1037.  
  1038.       while (imsg == NULL && (real_imsg = (struct IntuiMessage *)
  1039.                                GetMsg(uport))) {
  1040.      struct ExtendedGadget  *egad;
  1041.  
  1042.      switch (real_imsg->Class) {
  1043.         case GADGETDOWN :
  1044.            egad = (struct ExtendedGadget *)real_imsg->IAddress;
  1045.            if (egad->eg_Gadget.MutualExclude == ISUP_ID) {
  1046.           imsg = perform_gadget_action(egad, real_imsg);
  1047.           if ((egad->eg_Gadget.Activation & FOLLOWMOUSE) ||
  1048.                   egad->eg_Gadget.Activation == (GADGIMMEDIATE |
  1049.                                    RELVERIFY)) {
  1050.              struct GadgetList  *gl;
  1051.  
  1052.              /* Save active gadget and set auto repeat delay counter */
  1053.              gl                     = egad->eg_GadgetList;
  1054.              gl->gl_ActiveGadget    = egad;
  1055.              gl->gl_AutoRepeatDelay = ARROW_AUTO_REPEAT_START_DELAY;
  1056.           }
  1057.            } else {
  1058.           egad = NULL;   /* return imsg later */
  1059.            }
  1060.            break;
  1061.  
  1062.         case GADGETUP :
  1063.            egad = (struct ExtendedGadget *)real_imsg->IAddress;
  1064.            if (egad->eg_Gadget.MutualExclude == ISUP_ID) {
  1065.           imsg = perform_gadget_action(egad, real_imsg);
  1066.  
  1067.           /* Reset saved active gadget */
  1068.           egad->eg_GadgetList->gl_ActiveGadget = NULL;
  1069.             } else {
  1070.           egad = NULL;   /* return imsg later */
  1071.            }
  1072.            break;
  1073.  
  1074.         case MOUSEMOVE :
  1075.            if (egad = get_active_gadget(real_imsg->IDCMPWindow)) {
  1076.           imsg = perform_gadget_action(egad, real_imsg);
  1077.            }
  1078.            break;
  1079.  
  1080.         case INTUITICKS :
  1081.            if ((egad = get_active_gadget(real_imsg->IDCMPWindow))
  1082.                     && (egad->eg_Gadget.Flags &    SELECTED)) {
  1083.           if (egad->eg_Gadget.Activation == (GADGIMMEDIATE |
  1084.                                    RELVERIFY)) {
  1085.              struct GadgetList  *gl = egad->eg_GadgetList;
  1086.  
  1087.              /* Check auto repeat delay counter */
  1088.              if (gl->gl_AutoRepeatDelay) {
  1089.             gl->gl_AutoRepeatDelay--;
  1090.              } else {
  1091.             imsg = perform_gadget_action(egad, real_imsg);
  1092.              }
  1093.           }
  1094.            }
  1095.            break;
  1096.  
  1097.         case VANILLAKEY :
  1098.            if (egad = get_hotkey_gadget(real_imsg->IDCMPWindow,
  1099.                              real_imsg->Code)) {
  1100.           if (!(egad->eg_Gadget.Flags & GADGDISABLED)) {
  1101.              imsg = perform_hotkey_action(egad, real_imsg);
  1102.           }
  1103.            }
  1104.            break;
  1105.  
  1106.         default :
  1107.            if (egad = get_active_gadget(real_imsg->IDCMPWindow)) {
  1108.           egad->eg_GadgetList->gl_ActiveGadget = NULL;
  1109.           egad = NULL;   /* return imsg later */
  1110.            }
  1111.            break;
  1112.      }
  1113.      if (!imsg) {
  1114.  
  1115.         /* If isup msg then reply it, else return it */
  1116.         if (egad) {
  1117.            ReplyMsg((struct Message *)real_imsg);
  1118.         } else {
  1119.            imsg = real_imsg;
  1120.         }
  1121.      }
  1122.       }
  1123.    }
  1124.    return(imsg);
  1125. }
  1126.     /* Reply intuition message and free ISUP message if any */
  1127.  
  1128.    VOID
  1129. reply_msg(struct IntuiMessage  *imsg)
  1130. {
  1131.    if (imsg) {
  1132.       if (imsg->Class == ISUP_ID) {
  1133.      struct IntuiMessage  *real_imsg = *(struct IntuiMessage **)
  1134.                                  (imsg + 1);
  1135.      /* Free ISUP msg */
  1136.      FreeMem(imsg, (LONG)(sizeof(struct IntuiMessage) +
  1137.                         sizeof(struct IntuiMessage *)));
  1138.      /* Return real intui msg (ptr direct after ISUP msg) */
  1139.      imsg = real_imsg;
  1140.       }
  1141.       ReplyMsg((struct Message *)imsg);
  1142.    }
  1143. }
  1144.     /* Perform ISUP gadget action */
  1145.  
  1146.    STATIC struct IntuiMessage *
  1147. perform_gadget_action(struct ExtendedGadget  *egad,
  1148.                         struct IntuiMessage  *real_imsg)
  1149. {
  1150.    struct IntuiMessage    *imsg = NULL;
  1151.    struct Gadget          *gad = &egad->eg_Gadget;
  1152.    struct GadgetList      *gl = egad->eg_GadgetList;
  1153.    USHORT data_entry = egad->eg_DataEntry;
  1154.    struct ExtendedGadget  *real_egad = gl->gl_Gadgets[data_entry];
  1155.    struct MXData          *mx;
  1156.    struct ListViewData    *lv;
  1157.    struct PaletteData     *pd;
  1158.    VOID   *data = (VOID *)(real_egad + 1);
  1159.    USHORT type = egad->eg_Type;
  1160.    ULONG  min, max, num, flags = real_egad->eg_DataFlags, value = 0,
  1161.       class = real_imsg->Class, qualifier = real_imsg->Qualifier;
  1162.  
  1163.    switch (type) {
  1164.       case EXTENDED_GADGET_TYPE_BUTTON :
  1165.      if ((flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) &&
  1166.                           (gad->Flags & SELECTED)) {
  1167.         /* Prepare gadget state manually (selected) */
  1168.         change_gadget(real_egad);
  1169.         value = 1;
  1170.      }
  1171.      change_gadget(real_egad);
  1172.      break;
  1173.  
  1174.       case EXTENDED_GADGET_TYPE_CHECK :
  1175.      if (gad->Flags & SELECTED) {
  1176.         value = 1;
  1177.      }
  1178.      break;
  1179.  
  1180.       case EXTENDED_GADGET_TYPE_MX :
  1181.      mx = data;
  1182.      if (mx->mx_ActiveEntry != egad->eg_Gadget.GadgetID) {
  1183.         mx->mx_ActiveEntry = value = egad->eg_Gadget.GadgetID;
  1184.      } else {
  1185.         real_imsg = NULL;
  1186.      }
  1187.      change_gadget(real_egad);
  1188.      break;
  1189.  
  1190.       case EXTENDED_GADGET_TYPE_STRING :
  1191.       case EXTENDED_GADGET_TYPE_INTEGER :
  1192.      if (!(qualifier & QUALIFIER_ALT) &&
  1193.                (flags & GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE)) {
  1194.         struct InputData  *id = data;
  1195.         USHORT next_input;
  1196.  
  1197.         if (qualifier & QUALIFIER_SHIFT) {
  1198.            next_input = id->id_ActivatePrev;
  1199.         } else {
  1200.            next_input = id->id_ActivateNext;
  1201.         }
  1202.         activate_input_gadget(gl, next_input);
  1203.      }
  1204.      if (type == EXTENDED_GADGET_TYPE_STRING) {
  1205.         value = (ULONG)((struct StringInfo *)gad->SpecialInfo)->Buffer;
  1206.      } else {
  1207.         value = (ULONG)((struct StringInfo *)gad->SpecialInfo)->LongInt;
  1208.      }
  1209.      break;
  1210.  
  1211.       case EXTENDED_GADGET_TYPE_SLIDER_PROP :
  1212.      if (class == GADGETUP) {
  1213.         change_gadget(real_egad);
  1214.         real_imsg = NULL;
  1215.      } else {
  1216.         struct SliderData  *sl = data;
  1217.         struct PropInfo    *pi = (struct PropInfo *)gad->SpecialInfo;
  1218.  
  1219.         min = sl->sl_Min;
  1220.         max = (LONG)sl->sl_Max - (LONG)min;
  1221.         if (flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  1222.            num = max - ((LONG)get_prop_pos(max + 1, 1L, pi->VertPot) -
  1223.                                  (LONG)min);
  1224.         } else {
  1225.            num = (LONG)get_prop_pos(max + 1, 1L, pi->HorizPot) +
  1226.                                   (LONG)min;
  1227.         }
  1228.         if (sl->sl_Level != num) {
  1229.            sl->sl_Level = value = num;
  1230.         } else {
  1231.            real_imsg = NULL;
  1232.         }
  1233.      }
  1234.      break;
  1235.  
  1236.       case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
  1237.      if (class == GADGETUP) {
  1238.         change_gadget(real_egad);
  1239.         real_imsg = NULL;
  1240.      } else {
  1241.         struct ScrollerData  *sc = data;
  1242.         struct PropInfo      *pi = (struct PropInfo *)gad->SpecialInfo;
  1243.  
  1244.         min = sc->sc_Visible;
  1245.         max = sc->sc_Total;
  1246.         if (flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  1247.            num = get_prop_pos(max, min, pi->VertPot);
  1248.         } else {
  1249.            num = get_prop_pos(max, min, pi->HorizPot);
  1250.         }
  1251.         if (sc->sc_Top != num) {
  1252.            sc->sc_Top = value = num;
  1253.         } else {
  1254.            real_imsg = NULL;
  1255.         }
  1256.      }
  1257.      break;
  1258.  
  1259.       case EXTENDED_GADGET_TYPE_SCROLLER_LEFT :
  1260.       case EXTENDED_GADGET_TYPE_SCROLLER_DOWN :
  1261.      if (class == GADGETUP) {
  1262.         real_imsg = NULL;
  1263.      } else {
  1264.         struct ScrollerData  *sc = data;
  1265.  
  1266.         num = sc->sc_Top;
  1267.         if (num > 0) {
  1268.            sc->sc_Top = value = num - 1;
  1269.            change_gadget(real_egad);
  1270.         } else {
  1271.            real_imsg = NULL;
  1272.         }
  1273.      }
  1274.      break;
  1275.  
  1276.       case EXTENDED_GADGET_TYPE_SCROLLER_RIGHT :
  1277.       case EXTENDED_GADGET_TYPE_SCROLLER_UP :
  1278.      if (class == GADGETUP) {
  1279.         real_imsg = NULL;
  1280.      } else {
  1281.         struct ScrollerData  *sc = data;
  1282.  
  1283.         num = sc->sc_Top;
  1284.         min = sc->sc_Visible;
  1285.         max = sc->sc_Total;
  1286.         num++;
  1287.         if (num < max && (max - num) >= min) {
  1288.            sc->sc_Top = value = num;
  1289.            change_gadget(real_egad);
  1290.         } else {
  1291.            real_imsg = NULL;
  1292.         }
  1293.      }
  1294.      break;
  1295.  
  1296.       case EXTENDED_GADGET_TYPE_CYCLE :
  1297.      if (change_cycle_gadget(real_egad, qualifier) == TRUE) {
  1298.         value = ((struct CycleData *)data)->cy_ActiveEntry;
  1299.      } else {
  1300.         real_imsg = NULL;
  1301.      }
  1302.      break;
  1303.  
  1304.       case EXTENDED_GADGET_TYPE_COUNT :
  1305.      change_count_gadget(real_egad);
  1306.      value = ((struct CountData *)data)->co_Value;
  1307.      break;
  1308.  
  1309.       case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
  1310.      if (class == GADGETUP) {
  1311.         change_gadget(real_egad);
  1312.      } else {
  1313.         lv  = data;
  1314.         min = lv->lv_VisibleEntries;
  1315.         max = lv->lv_ListEntries;
  1316.         num = get_prop_pos(max, min, ((struct PropInfo *)
  1317.                         gad->SpecialInfo)->VertPot);
  1318.         if ((min = lv->lv_TopEntry) != num) {
  1319.            struct Node  *node = lv->lv_TopNode;
  1320.            USHORT i;
  1321.  
  1322.            if (min > num) {
  1323.           for (i = min - num; i > 0; i--) {
  1324.              node = node->ln_Pred;
  1325.           }
  1326.            } else {
  1327.           for (i = num - min; i > 0; i--) {
  1328.              node = node->ln_Succ;
  1329.           }
  1330.            }
  1331.            lv->lv_TopNode  = node;
  1332.            lv->lv_TopEntry = num;
  1333.            if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  1334.           print_list_view_text(egad);
  1335.            }
  1336.         }
  1337.      }
  1338.      real_imsg = NULL;
  1339.      break;
  1340.  
  1341.       case EXTENDED_GADGET_TYPE_LISTVIEW_UP :
  1342.      if (class != GADGETUP) {
  1343.         lv  = data;
  1344.         num = lv->lv_TopEntry;
  1345.         if (num > 0) {
  1346.            lv->lv_TopNode  = lv->lv_TopNode->ln_Pred;
  1347.            lv->lv_TopEntry = value = num - 1;
  1348.            change_gadget(real_egad);
  1349.         }
  1350.      }
  1351.      real_imsg = NULL;
  1352.      break;
  1353.  
  1354.       case EXTENDED_GADGET_TYPE_LISTVIEW_DOWN :
  1355.      if (class != GADGETUP) {
  1356.         lv  = data;
  1357.         min = lv->lv_VisibleEntries;
  1358.         max = lv->lv_ListEntries;
  1359.         num = lv->lv_TopEntry + 1;
  1360.         if (num < max && (max - num) >= min) {
  1361.            lv->lv_TopNode  = lv->lv_TopNode->ln_Succ;
  1362.            lv->lv_TopEntry = value = num;
  1363.            change_gadget(real_egad);
  1364.         }
  1365.      }
  1366.      real_imsg = NULL;
  1367.      break;
  1368.  
  1369.       case EXTENDED_GADGET_TYPE_LISTVIEW_ENTRY :
  1370.      lv  = data;
  1371.      max = lv->lv_ListEntries;
  1372.      num = lv->lv_TopEntry + egad->eg_Gadget.GadgetID;
  1373.      if (num < max && num != lv->lv_SelectedEntry) {
  1374.         lv->lv_SelectedEntry = value = num;
  1375.         if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  1376.            change_gadget(real_egad);
  1377.         }
  1378.      } else {
  1379.         real_imsg = NULL;
  1380.      }
  1381.      break;
  1382.  
  1383.       case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
  1384.      real_imsg = NULL;
  1385.      break;
  1386.  
  1387.       case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
  1388.      pd  = data;
  1389.      num = egad->eg_Gadget.GadgetID;
  1390.      if (num != pd->pd_ActiveColor) {
  1391.         pd->pd_ActiveColor = value = num;
  1392.         change_gadget(real_egad);
  1393.      } else {
  1394.         real_imsg = NULL;
  1395.      }
  1396.      break;
  1397.    }
  1398.    if (real_imsg) {
  1399.       imsg = create_intui_message(real_imsg, gl, data_entry, value);
  1400.    }
  1401.    return(imsg);
  1402. }
  1403.     /* Perform hotkey gadget action */
  1404.  
  1405.    STATIC struct IntuiMessage *
  1406. perform_hotkey_action(struct ExtendedGadget  *egad,
  1407.                         struct IntuiMessage  *real_imsg)
  1408. {
  1409.    struct IntuiMessage    *imsg = NULL;
  1410.    struct Gadget          *gad = &egad->eg_Gadget;
  1411.    struct GadgetList      *gl = egad->eg_GadgetList;
  1412.    struct Window          *win = gl->gl_Window;
  1413.    struct RastPort        *rp = win->RPort;
  1414.    USHORT data_entry = egad->eg_DataEntry;
  1415.    struct ExtendedGadget  *real_egad = gl->gl_Gadgets[data_entry];
  1416.    struct MXData          *mx;
  1417.    struct SliderData      *sl;
  1418.    struct ScrollerData    *sc;
  1419.    struct CycleData       *cy;
  1420.    struct CountData       *co;
  1421.    struct ListViewData    *lv;
  1422.    struct PaletteData     *pd;
  1423.    VOID  *data = (VOID *)(real_egad + 1);
  1424.    ULONG min, max, num, flags = real_egad->eg_DataFlags, value = 0,
  1425.      qualifier = real_imsg->Qualifier & QUALIFIER_SHIFT;
  1426.  
  1427.    switch (egad->eg_Type) {
  1428.       case EXTENDED_GADGET_TYPE_BUTTON :
  1429.      if (flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) {
  1430.         if (gad->Flags & SELECTED) {
  1431.  
  1432.            /* Prepare gadget state manually (selected) */
  1433.            change_gadget(real_egad);
  1434.            gad->Flags &= ~SELECTED;
  1435.         } else {
  1436.            gad->Flags |= SELECTED;
  1437.            value       = 1;
  1438.         }
  1439.      } else {
  1440.         if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  1441.            gad->Flags |= SELECTED;
  1442.            change_gadget(real_egad);
  1443.            timer_delay(0L, 100000L);
  1444.  
  1445.            /* Prepare gadget state manually (unselected) */
  1446.            change_gadget(real_egad);
  1447.            gad->Flags &= ~SELECTED;
  1448.         }
  1449.      }
  1450.      change_gadget(real_egad);
  1451.      break;
  1452.  
  1453.       case EXTENDED_GADGET_TYPE_CHECK :
  1454.      if (gad->Flags & SELECTED) {
  1455.         gad->Flags &= ~SELECTED;
  1456.      } else {
  1457.         gad->Flags |= SELECTED;
  1458.         value       = 1;
  1459.      }
  1460.      change_gadget(real_egad);
  1461.      break;
  1462.  
  1463.       case EXTENDED_GADGET_TYPE_MX :
  1464.      mx  = data;
  1465.      max = mx->mx_TextEntries;
  1466.      num = mx->mx_ActiveEntry;
  1467.      if (qualifier) {
  1468.         if (num > 0) {
  1469.            num--;
  1470.         } else {
  1471.            num = max - 1;
  1472.         }
  1473.      } else {
  1474.         if (num < (max - 1)) {
  1475.            num++;
  1476.         } else {
  1477.            num = 0;
  1478.         }
  1479.      }
  1480.      mx->mx_ActiveEntry = value = num;
  1481.      change_gadget(real_egad);
  1482.      break;
  1483.  
  1484.       case EXTENDED_GADGET_TYPE_STRING :
  1485.       case EXTENDED_GADGET_TYPE_INTEGER :
  1486.      activate_input_gadget(gl, data_entry);
  1487.      real_imsg = NULL;
  1488.      break;
  1489.  
  1490.       case EXTENDED_GADGET_TYPE_SLIDER_PROP :
  1491.      sl  = data;
  1492.      min = sl->sl_Min;
  1493.      max = sl->sl_Max;
  1494.      num = sl->sl_Level;
  1495.      if (qualifier) {
  1496.         if ((LONG)num > (LONG)min) {
  1497.            num--;
  1498.         } else {
  1499.            real_imsg = NULL;
  1500.         }
  1501.      } else {
  1502.         if ((LONG)num < (LONG)max) {
  1503.            num++;
  1504.         } else {
  1505.            real_imsg = NULL;
  1506.         }
  1507.      }
  1508.      if (real_imsg) {
  1509.         sl->sl_Level = value = num;
  1510.         change_gadget(real_egad);
  1511.      }
  1512.      break;
  1513.  
  1514.       case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
  1515.      sc  = data;
  1516.      min = sc->sc_Visible;
  1517.      max = sc->sc_Total;
  1518.      num = sc->sc_Top;
  1519.      if (qualifier) {
  1520.         if (num > 0) {
  1521.            num--;
  1522.         } else {
  1523.            real_imsg = NULL;
  1524.         }
  1525.      } else {
  1526.         if (num < (max - min)) {
  1527.            num++;
  1528.         } else {
  1529.            real_imsg = NULL;
  1530.         }
  1531.      }
  1532.      if (real_imsg) {
  1533.         sc->sc_Top = value = num;
  1534.         change_gadget(real_egad);
  1535.      }
  1536.      break;
  1537.  
  1538.       case EXTENDED_GADGET_TYPE_CYCLE :
  1539.      cy  = data;
  1540.      max = cy->cy_TextEntries;
  1541.      num = cy->cy_ActiveEntry;
  1542.      if (qualifier) {
  1543.         if (num > 0) {
  1544.            num--;
  1545.         } else {
  1546.            num = max - 1;
  1547.         }
  1548.      } else {
  1549.         if (num < (max - 1)) {
  1550.            num++;
  1551.         } else {
  1552.            num = 0;
  1553.         }
  1554.      }
  1555.      if (cy->cy_ActiveEntry != num) {
  1556.         cy->cy_ActiveEntry = value = num;
  1557.         change_gadget(real_egad);
  1558.      } else {
  1559.         real_imsg = NULL;
  1560.      }
  1561.      break;
  1562.  
  1563.       case EXTENDED_GADGET_TYPE_COUNT :
  1564.      co  = data;
  1565.      min = co->co_Min;
  1566.      max = co->co_Max;
  1567.      num = co->co_Value;
  1568.      if (qualifier) {
  1569.         if ((LONG)num > (LONG)min) {
  1570.            num--;
  1571.         } else {
  1572.            real_imsg = NULL;
  1573.         }
  1574.      } else {
  1575.         if ((LONG)num < (LONG)max) {
  1576.            num++;
  1577.         } else {
  1578.            real_imsg = NULL;
  1579.         }
  1580.      }
  1581.      if (real_imsg) {
  1582.         co->co_Value = value = num;
  1583.         change_gadget(real_egad);
  1584.      }
  1585.      break;
  1586.  
  1587.       case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
  1588.      lv  = data;
  1589.      min = lv->lv_VisibleEntries;
  1590.      max = lv->lv_ListEntries;
  1591.      if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  1592.         num = lv->lv_SelectedEntry;
  1593.      } else {
  1594.         num = lv->lv_TopEntry;
  1595.      }
  1596.      if (qualifier) {
  1597.         if (num > 0) {
  1598.            num--;
  1599.         } else {
  1600.            real_imsg = NULL;
  1601.         }
  1602.      } else {
  1603.         if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  1604.            if (++num >= max) {
  1605.           real_imsg = NULL;
  1606.            }
  1607.         } else {
  1608.            if (++num >= max || (max - num) < min) {
  1609.           real_imsg = NULL;
  1610.            }
  1611.         }
  1612.      }
  1613.      if (real_imsg) {
  1614.         set_gadget_attributes(gl, data_entry, 0L, 0L, USE_CURRENT_VALUE,
  1615.                         num, (VOID *)USE_CURRENT_VALUE);
  1616.         if (flags & GADGET_DATA_FLAG_LISTVIEW_SHOW_SELECTED) {
  1617.            value = lv->lv_SelectedEntry;
  1618.         } else {
  1619.            real_imsg = NULL;
  1620.         }
  1621.      }
  1622.      break;
  1623.  
  1624.       case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
  1625.       case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
  1626.      pd  = data;
  1627.      min = pd->pd_ColorOffset;
  1628.      max = pd->pd_MaxColors;
  1629.      num = pd->pd_ActiveColor;
  1630.      if (qualifier) {
  1631.         if ((LONG)num > (LONG)min) {
  1632.            num--;
  1633.         } else {
  1634.            num = min + max - 1;
  1635.         }
  1636.      } else {
  1637.         if ((LONG)num < (LONG)(min + max - 1)) {
  1638.            num++;
  1639.         } else {
  1640.            num = min;
  1641.         }
  1642.      }
  1643.      pd->pd_ActiveColor = value = num;
  1644.      change_gadget(real_egad);
  1645.      break;
  1646.    }
  1647.    if (real_imsg) {
  1648.       imsg = create_intui_message(real_imsg, gl, data_entry, value);
  1649.    }
  1650.    return(imsg);
  1651. }
  1652.     /* Create special ISUP intui message */
  1653.  
  1654.    STATIC struct IntuiMessage *
  1655. create_intui_message(struct IntuiMessage  *real_imsg, struct GadgetList  *gl,
  1656.                          USHORT data_entry,    ULONG value)
  1657. {
  1658.    struct IntuiMessage  *imsg = NULL;
  1659.  
  1660.    if (!(imsg = AllocMem((LONG)(sizeof(struct IntuiMessage) +
  1661.      sizeof(struct IntuiMessage *)), (LONG)MEMF_PUBLIC | MEMF_CLEAR))) {
  1662.       imsg = real_imsg;
  1663.    } else {
  1664.  
  1665.       /* Init ISUP intui message */
  1666.       imsg->Class       = ISUP_ID;
  1667.       imsg->Code        = data_entry;
  1668.       imsg->IAddress    = (APTR)value;
  1669.       imsg->SpecialLink = (struct IntuiMessage *)gl;
  1670.  
  1671.       /* Put real IntuiMessage ptr direct after ISUP intuition message */
  1672.       *(struct IntuiMessage **)(imsg + 1) = real_imsg;
  1673.    }
  1674.    return(imsg);
  1675. }
  1676.     /* Get active gadget for given window */
  1677.  
  1678.    STATIC struct ExtendedGadget *
  1679. get_active_gadget(struct Window  *win)
  1680. {
  1681.    struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  1682.    struct ExtendedGadget      *egad = NULL;
  1683.    USHORT count;
  1684.  
  1685.    ObtainSemaphore(&vg->vg_Semaphore);
  1686.    if (count = vg->vg_Count) {
  1687.       struct GadgetList  *gl = (struct GadgetList *)vg->vg_MinList.mlh_Head;
  1688.       USHORT i;
  1689.  
  1690.       for (i = 0; i < count; i++) {
  1691.      if (gl->gl_Window == win && gl->gl_ActiveGadget) {
  1692.         egad = gl->gl_ActiveGadget;
  1693.         break;
  1694.  
  1695.      }
  1696.      gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
  1697.       }
  1698.    }
  1699.    ReleaseSemaphore(&vg->vg_Semaphore);
  1700.    return(egad);
  1701. }
  1702.     /* Get hotkey gadget for given window */
  1703.  
  1704.    STATIC struct ExtendedGadget *
  1705. get_hotkey_gadget(struct Window  *win, USHORT hotkey)
  1706. {
  1707.    struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  1708.    struct ExtendedGadget      *result_egad = NULL;
  1709.    USHORT count;
  1710.  
  1711.    ObtainSemaphore(&vg->vg_Semaphore);
  1712.    if (count = vg->vg_Count) {
  1713.       struct GadgetList  *gl = (struct GadgetList *)vg->vg_MinList.mlh_Head;
  1714.       USHORT i;
  1715.       BOOL   found = FALSE;
  1716.  
  1717.       hotkey = toupper(hotkey);
  1718.       for (i = 0; i < count && found == FALSE; i++) {
  1719.      if (gl->gl_Window == win) {
  1720.         USHORT j, data_entries = gl->gl_DataEntries;
  1721.  
  1722.         for (j = 0; j < data_entries && found == FALSE; j++) {
  1723.            struct ExtendedGadget  *egad = gl->gl_Gadgets[j];
  1724.  
  1725.            if (egad->eg_Flags & EXTENDED_GADGET_FLAG_HOTKEY &&
  1726.                        toupper(egad->eg_Hotkey) == hotkey) {
  1727.           result_egad = egad;
  1728.           found       = TRUE;
  1729.            }
  1730.         }
  1731.      }
  1732.      gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
  1733.       }
  1734.    }
  1735.    ReleaseSemaphore(&vg->vg_Semaphore);
  1736.    return(result_egad);
  1737. }
  1738.     /* Find first visible gadget list for given window */
  1739.  
  1740.    struct GadgetList  *
  1741. get_first_gadget_list(struct Window  *win)
  1742. {
  1743.    struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  1744.    struct GadgetList          *gl, *gl_return = NULL;
  1745.  
  1746.    ObtainSemaphore(&vg->vg_Semaphore);
  1747.    gl = (struct GadgetList *)&vg->vg_MinList.mlh_Head;
  1748.    while (gl->gl_MinNode.mln_Succ) {
  1749.       if (gl->gl_Window == win) {
  1750.      gl_return = gl;
  1751.      break;
  1752.       }
  1753.       gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
  1754.    }
  1755.    ReleaseSemaphore(&vg->vg_Semaphore);
  1756.    return(gl_return);
  1757. }
  1758.